<!-- vue2+elementUI顶部可收起展开搜索组件 -->
<!-- emit:
1. onQuery: 点击搜索按钮时触发，返回搜索条件对象
2. onReset: 点击重置按钮时触发，返回搜索条件对象
3. selectChange: 下拉框选择时触发，返回当前选择项
4. checkboxChange: 复选框选择时触发，返回当前选择项
5. radioChange: 单选框选择时触发，返回当前选择项
6. toggle: 点击收起展开按钮时触发，返回当前展开状态和搜索项高度 -->
<!-- props：
spanPercentage: 每个搜索项的宽度百分比，默认为33.3
queryDisabled: 是否禁用搜索按钮，默认为false
searchOptions: 搜索项配置数组，每个对象包含以下属性：
  label: 搜索项名称，必填
  type: 搜索项类型，必填，可选值为input、select、checkBox、radioGroup、rangeInput、datetimeRange、dateRange、datetime
  spanPercentage: 搜索项的宽度百分比，默认为33.3 可选 
  labelWidth: 搜索项的label宽度，默认为auto 可选 
  dontClearable: 是否禁用清除按钮，默认为false 可选 
  以上是所有搜索项都有的属性，以下是根据type不同而不同的属性：
1.input
  - type: 'input'
  - label: 搜索项名称
  - key:字段名
  - value:字段值，也是默认值
2.rangeInput
  - type: rangeInput
  - label: 搜索项名称
  - key1: 第一个输入框的字段名
  - key2: 第二个输入框的字段名
  - value1: 第一个输入框的字段值
  - value2: 第二个输入框的字段值
3.datetimeRange
  - type: datetimeRange
  - label: 搜索项名称
  - key: 字段名
  - value: 字段值，也是默认值
  - valueFormat: 日期格式，默认为'yyyy-MM-dd HH:mm'
4.checkBox
  - type: checkBox
  - label: 搜索项名称
  - options: 选项数组，每个对象包含以下属性：
    - key: 选项字段名
    - label: 选项名称
    - value: 选项值
    - span: 选项的宽度百分比，默认为8
5.radioGroup
  - type: radioGroup
  - label: 搜索项名称
  - key: 字段名
  - value: 字段值，也是默认值
  - options: 选项数组，每个对象包含以下属性：
    - label: 选项名称
    - value: 选项值
    - span: 选项的宽度百分比，默认为8
6.select
  - type: select
  - label: 搜索项名称
  - key: 字段名
  - value: 字段值，也是默认值
  - options: 选项数组，每个对象包含以下属性：
    - label: 选项名称
    - value: 选项值 -->

<template>
  <el-form
    :inline="true"
    size="small"
    :model="formInline"
    class="demo-form-inline"
    ref="formInline"
    label-width="auto"
  >
    <div
      class="search-conditions"
      :class="{ expanded: isExpanded }"
      :style="{ maxHeight: needMaxHeight ? '53px' : 'none' }"
    >
      <el-form-item
        :style="{
          flex: `0 0 calc(${item.spanPercentage || spanPercentage}% - 20px)`,
        }"
        :label="item.label"
        :label-width="item.labelWidth || 'auto'"
        v-for="item in searchOptions"
        :key="item.key"
        :prop="item.key"
      >
        <el-input
          v-if="item.type == 'input'"
          v-model="formInline[item.key]"
          :isClearable="item.dontClearable ? false : true"
        ></el-input>

        <div class="range-input" v-else-if="item.type == 'rangeInput'">
          <el-col :span="11">
            <el-form-item :prop="item.key1">
              <el-input
                v-model="formInline[item.key1]"
                placeholder="请输入"
                size="small"
                clearable
              ></el-input>
            </el-form-item>
          </el-col>
          <el-col class="line" :span="2" style="text-align: center">-</el-col>
          <el-col :span="11">
            <el-form-item :prop="item.key2">
              <el-input
                v-model="formInline[item.key2]"
                placeholder="请输入"
                size="small"
                clearable
              ></el-input>
            </el-form-item>
          </el-col>
        </div>

        <el-select
          v-else-if="item.type == 'select'"
          v-model="formInline[item.key]"
          @change="selectChange(item)"
        >
          <el-option
            :isClearable="item.dontClearable ? false : true"
            v-for="iitem in item.options"
            :key="iitem.value"
            :label="iitem.label"
            :value="iitem.value"
          ></el-option>
        </el-select>

        <el-date-picker
          v-else-if="item.type == 'datetimeRange'"
          size="small"
          v-model="formInline[item.key]"
          type="datetimerange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :value-format="
            item.valueFormat ? item.valueFormat : 'yyyy-MM-dd HH:mm'
          "
          :format="item.valueFormat ? item.valueFormat : 'yyyy-MM-dd HH:mm'"
          :default-time="['00:00:00', '23:59:00']"
        >
        </el-date-picker>

        <el-date-picker
          v-else-if="item.type == 'dateRange'"
          size="small"
          style="flex: 1"
          v-model="formInline[item.key]"
          value-format="yyyy-MM-dd"
          type="daterange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :clearable="item.clearable"
        >
        </el-date-picker>

        <!-- 有指定时间格式就用指定格式,否则用默认的格式 -->
        <el-date-picker
          v-else-if="item.type == 'date' || item.type == 'datetime'"
          size="small"
          v-model="formInline[item.key]"
          :type="item.type"
          placeholder="选择日期"
          :value-format="
            item.valueFormat
              ? item.valueFormat
              : item.type == 'date'
              ? 'yyyy-MM-dd'
              : 'yyyy-MM-dd HH:mm'
          "
          :format="
            item.valueFormat
              ? item.valueFormat
              : item.type == 'date'
              ? 'yyyy-MM-dd'
              : 'yyyy-MM-dd HH:mm'
          "
        >
        </el-date-picker>

        <div class="check-box" v-else-if="item.type == 'checkBox'">
          <el-col
            :span="iitem.span ? iitem.span : 8"
            v-for="iitem in item.options"
            :key="iitem.key"
          >
            <el-form-item :prop="iitem.key">
              <el-checkbox
                @change="checkboxChange(item)"
                v-model="formInline[iitem.key]"
                >{{ iitem.label }}</el-checkbox
              >
            </el-form-item>
          </el-col>
        </div>

        <el-radio-group
          v-model="formInline[item.key]"
          @change="radioChange(item)"
          v-else-if="item.type == 'radioGroup'"
        >
          <el-col
            class="flex-center"
            v-for="(iitem, index) in item.options"
            :key="iitem.key"
            :span="iitem.span ? iitem.span : 8"
          >
            <el-radio :label="iitem.value" :key="index">{{
              iitem.label
            }}</el-radio>
          </el-col>
        </el-radio-group>
        <el-input
          v-else
          v-model="formInline[item.key]"
          :isClearable="item.dontClearable ? false : true"
        ></el-input>
      </el-form-item>
      <el-form-item
        style="text-align: left; flex: 1"
        v-if="(isExpanded || !needMaxHeight) && waitShow"
      >
        <el-button
          size="small"
          type="primary"
          icon="el-icon-search"
          :disabled="queryDisabled"
          @click="onQuery"
          >查询</el-button
        >
        <el-button
          size="small"
          icon="el-icon-refresh"
          @click="onReset('formInline')"
          >重置</el-button
        >
        <span
          style="cursor: pointer; color: #66b1ff; margin-left: 10px"
          @click="toggleExpand"
          v-if="needMaxHeight"
        >
          {{ isExpanded ? "收起" : "展开" }}
          <i
            style="color: #66b1ff"
            :class="isExpanded ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
          ></i>
        </span>
      </el-form-item>
    </div>
    <el-form-item style="text-align: right" v-if="!isExpanded && needMaxHeight">
      <el-button
        type="primary"
        icon="el-icon-search"
        :disabled="queryDisabled"
        @click="onQuery"
        >查询</el-button
      >
      <el-button icon="el-icon-refresh" @click="onReset('formInline')"
        >重置</el-button
      >
      <span
        style="cursor: pointer; color: #66b1ff; margin-left: 10px"
        @click="toggleExpand"
        v-if="needMaxHeight"
      >
        {{ isExpanded ? "收起" : "展开" }}
        <i
          style="color: #66b1ff"
          :class="isExpanded ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
        ></i>
      </span>
    </el-form-item>
  </el-form>
</template>
<script>
export default {
  name: "topSearcher",
  data() {
    return {
      waitShow: false,
      searchHeight: 53,
      // 初始化 formInline 对象，包含所有可能的属性,必须用$set来设置属性否则无法实现响应式,页面表现就是输入框数据不会更新,输入无效果
      formInline: this.initializeFormInline(),
      isExpanded: false,
    };
  },
  props: {
    //搜索项占宽百分比(在searchOptions中也有此字段,用于单独设置某个搜索项的宽度,如时间范围这种比较长的)
    spanPercentage: {
      type: Number,
      default: 33.3,
    },
    //搜索项
    searchOptions: {
      type: Array,
      required: true,
    },
    //禁用搜索
    queryDisabled: {
      type: Boolean,
      default: false,
    },
  },
  computed: {
    needMaxHeight() {
      // 判断是否需要设置最大高度用于实现收起展开的效果
      return this.searchHeight > 53 ? true : false;
    },
  },
  mounted() {
    // 获取未收缩的搜索条件高度（一行53px）
    const element = document.querySelector(".search-conditions");
    // 获取元素的高度
    const height = element.offsetHeight;
    if (height) {
      this.searchHeight = height;
    }
    this.$nextTick(() => {
      this.waitShow = true;
      this.onQuery();
    });
    // console.log("初始化的this.formInline", this.formInline);
  },
  methods: {
    initializeFormInline() {
      // 使用 reduce 方法初始化 formInline 对象
      return this.searchOptions.reduce((acc, item) => {
        switch (item.type) {
          case "rangeInput":
            this.$set(
              acc,
              item.key1,
              item.value1 !== undefined && item.value1 !== null
                ? item.value1
                : ""
            );
            this.$set(
              acc,
              item.key2,
              item.value2 !== undefined && item.value2 !== null
                ? item.value2
                : ""
            );
            break;
          case "checkBox":
            item.options.forEach((iitem) => {
              this.$set(
                acc,
                iitem.key,
                iitem.value !== undefined && iitem.value !== null
                  ? iitem.value
                  : ""
              );
            });
            break;
          default:
            this.$set(
              acc,
              item.key,
              item.value !== undefined && item.value !== null ? item.value : ""
            );
            break;
        }
        return acc;
      }, {});
    },
    //重置搜索条件事件
    onReset(formName) {
      this.$nextTick(() => {
        this.$refs[formName].resetFields();
        this.$emit("onReset", this.formInline);
      });
    },
    //查询事件
    onQuery() {
      this.$emit("onQuery", this.formInline);
    },
    //普通select下拉框change事件
    selectChange(item) {
      this.$emit("selectChange", item);
    },
    //多选框change事件
    checkboxChange(item) {
      this.$emit("checkboxChange", item);
    },
    //单选框change事件
    radioChange(item) {
      this.$emit("radioChange", item);
    },
    toggleExpand() {
      this.isExpanded = !this.isExpanded;
      this.$emit("toggle", {
        isExpanded: this.isExpanded,
        height: this.searchHeight,
      }); // 抛出点击事件
    },
  },
};
</script>
<style scoped>
.demo-form-inline {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: right;
  .el-form-item {
    /* 每个项目占据 1/3 的宽度，减去间距 */
    display: flex;
    flex: 0 0 calc(33.333% - 20px);
    margin: 10px;
    box-sizing: border-box;
    text-align: left;

    .el-form-item__label {
      width: 30%;
      /* 如果需要文字通过调整间距实现等宽 */
      /* text-align: justify;
      text-justify: distribute-all-lines;
      text-align-last: justify;
      font-weight: bold;  */
    }
    .el-form-item__content {
      flex: 1;
      .el-select,
      .el-date-editor,
      .el-range-editor {
        width: 100%;
      }
      .el-radio-group {
        width: 100%;
      }
    }
  }
  .search-conditions {
    /* 一行的高度 */
    /* max-height: 53px; */
    position: relative;
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-start;
    overflow: hidden;
    transition: max-height 0.3s ease; /* 平滑过渡效果 */
  }

  .search-conditions.expanded {
    max-height: none !important; /* 展开时移除最大高度限制 */
  }
}
.range-input {
  .el-form-item {
    margin: 0 !important;
    .el-form-item__content {
      width: 100% !important;
    }
  }
}
.check-box {
  .el-form-item {
    margin: 0 !important;
    .el-form-item__content {
      width: 100% !important;
    }
  }
}
.fixed-width {
  width: 200px; /* 设置一个固定的宽度 */
  border: 1px solid #000; /* 添加边框以便观察效果 */
  padding: 5px; /* 添加内边距 */
  box-sizing: border-box; /* 防止 padding 和 border 影响宽度 */
}
.flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>
